home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
gamesrc
/
arasan_s
/
bearing.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-31
|
13KB
|
523 lines
// Copyright 1992-3 by Jon Dart. All Rights Reserved.
#include "bearing.h"
#include "util.h"
#ifdef RANGE_CHECK
#include <assert.h>
#endif
#include "beardata.h"
const int RankIncr = 8; // add this to move 1 rank
static inline void
SetSquare(
const Square sq, Square * squares, unsigned &NumSquares)
{
#ifdef RANGE_CHECK
assert(sq.OnBoard());
assert (NumSquares < Bearing::MaxBearSq);
#endif
squares[NumSquares++] = sq;
}
static void
PawnMoves(const Board & board,
const ColorType side, const Square i,
Square * squares, unsigned &NumSquares, const Boolean attacks)
{
Square start, dest, dest2;
Piece piece;
if (!attacks)
{
start = i;
dest = (Direction[side] > 0) ? i + RankIncr : i - RankIncr;
if (dest.OnBoard())
{
piece = board[dest];
if (piece.IsEmpty())
{
// 1-square pawn advance
SetSquare(dest, squares, NumSquares);
if (i.Rank(board.Side()) == 2)
{
dest2 = (Direction[side] > 0) ?
dest + RankIncr : dest - RankIncr;
if (board[dest2].IsEmpty()) // 2-square advance
SetSquare(dest2, squares, NumSquares);
}
}
}
}
// check for possible captures
if (i.File() != 1)
{
dest = (Direction[side] > 0) ? i + (RankIncr - 1) :
i - (RankIncr + 1);
if (dest.OnBoard())
{
piece = board[dest];
if (attacks ||
(!piece.IsEmpty() && (piece.Color() != board.Side())))
SetSquare(dest, squares, NumSquares);
}
}
if (i.File() != 8)
{
dest = (Direction[side] > 0) ? i + (RankIncr + 1) :
i - (RankIncr - 1);
if (dest.OnBoard())
{
piece = board[dest];
if (attacks ||
(!piece.IsEmpty() && (piece.Color() != board.Side())))
SetSquare(dest, squares, NumSquares);
}
}
Square epsq = board.EnPassantSq(board.OppositeSide());
if (!epsq.IsInvalid() && !attacks)
{
if ((i.File() != 8 && i + 1 == epsq) ||
(i.File() != 1 && i - 1 == epsq))
{
Square dest(epsq + RankIncr * Direction[side]);
if (board[dest].IsEmpty())
SetSquare(dest, squares, NumSquares);
}
}
}
#define RBMoves(board, data, squares, NumSquares) \
Square i; \
while ((i = *data) != 255 && board[i].IsEmpty()) \
{ \
SetSquare(i,squares,NumSquares); \
++data; \
} \
if (i != 255 && board[i].Color() != side) \
SetSquare(i,squares,NumSquares) \
#define RBAttacks(board, data, squares, NumSquares) \
Square i; \
while ((i = *data) != 255 && board[i].IsEmpty()) \
{ \
SetSquare(i,squares,NumSquares); \
++data; \
} \
if (i != 255) \
SetSquare(i,squares,NumSquares) \
static void
KnightMoves(
const Board & board,
const Square loc,
Square * squares,
unsigned &NumSquares,
const Boolean attacks)
{
const ColorType side = board[loc].Color();
const byte *data = KnightSquares[(int)loc];
int i = 0;
while (i < 8 && *data != 255)
{
++i;
Square dest(*data++);
Piece piece = board[dest];
if ((piece.IsEmpty() || (attacks || piece.Color() != side)))
SetSquare(dest, squares, NumSquares);
}
}
static void
KingMoves(
const Board & board,
const Square loc,
Square * squares,
unsigned &NumSquares,
const Boolean attacks)
{
const ColorType side = board[loc].Color();
const byte *data = KingSquares[(int)loc];
for (int i = 0; i <8 && *data != 255 ;i++)
{
Square dest(*data++);
Piece piece = board[dest];
if ((piece.IsEmpty() || (attacks || piece.Color() != side)))
SetSquare(dest, squares, NumSquares);
}
}
unsigned
Bearing::BearSq(const Board & board,
const Square loc, Square * squares)
{
unsigned NumSquares = 0;
int j;
const ColorType side = board[loc].Color();
switch (board[loc].Type())
{
case Piece::Empty:
break;
case Piece::Pawn:
PawnMoves(board, side,
loc, squares, NumSquares, False);
break;
case Piece::Knight:
KnightMoves(board, loc, squares, NumSquares, False);
break;
case Piece::Bishop:
for (j = 0; j < 4; j++)
{
const byte *data = BishopSquares[loc] + (j*8);
RBMoves(board, data, squares, NumSquares);
}
break;
case Piece::Rook:
for (j = 0; j < 4; j++)
{
const byte *data = RookSquares[loc] + (j*8);
RBMoves(board, data, squares, NumSquares);
}
break;
case Piece::Queen:
for (j = 0; j < 4; j++)
{
const byte *data = BishopSquares[loc] + (j*8);
RBMoves(board, data, squares, NumSquares);
}
for (j = 0; j < 4; j++)
{
const byte *data = RookSquares[loc] + (j*8);
RBMoves(board, data, squares, NumSquares);
}
break;
case Piece::King:
KingMoves(board, loc, squares, NumSquares, False);
break;
case Piece::Invalid:
break;
}
return NumSquares;
}
unsigned
Bearing::Attack(const Board & board,
const Square loc, const ColorType side,
Square * squares,
Boolean indirect)
{
#ifdef RANGE_CHECK
assert(loc.OnBoard());
#endif
int index = 0;
int i, n;
Square square1, sq;
Piece my_pawn(Piece::Pawn, side);
if (side == Black)
{
if (board[loc].IsEmpty())
{
Square origin(loc-RankIncr);
if (origin.OnBoard() &&
board[origin] == my_pawn)
squares[index++] = origin;
if (loc.Rank(side) == 4 && board[origin].IsEmpty() &&
board[origin - RankIncr] == my_pawn)
squares[index++] = origin - RankIncr;
}
else if (loc.Rank(side) != 1)
{
// square is occupied, try pawn captures
if (loc.File() != 1 &&
board[loc - (RankIncr+1)] == my_pawn)
squares[index++] = loc - (RankIncr+1);
if (loc.File() != 8 &&
board[loc - (RankIncr-1)] == my_pawn)
squares[index++] = loc - (RankIncr-1);
}
}
else
{
if (board[loc].IsEmpty())
{
Square origin(loc+RankIncr);
if (origin.OnBoard() &&
board[origin] == my_pawn)
squares[index++] = origin;
if (loc.Rank(side) == 4 && board[origin].IsEmpty() &&
board[origin + RankIncr] == my_pawn)
squares[index++] = origin + RankIncr;
}
else if (loc.Rank(side) != 1)
{
if (loc.File() != 8 &&
board[loc + RankIncr+1] == my_pawn)
squares[index++] = loc + RankIncr + 1;
if (loc.File() != 1 &&
board[loc + RankIncr-1] == my_pawn)
squares[index++] = loc + RankIncr - 1;
}
}
Piece knight(Piece::Knight, side);
Piece king(Piece::King, side);
for (i = 0; i < 8; i++)
{
sq = KnightSquares[loc][i];
if (sq == 255)
break;
if (board[sq] == knight)
squares[index++] = sq;
}
for (i = 0; i <8; i++)
{
sq = KingSquares[loc][i];
if (sq == 255)
break;
if (board[sq] == king)
squares[index++] = sq;
}
n = index;
int offset;
Piece bishop(Piece::Bishop, side);
Piece queen(Piece::Queen, side);
Piece rook(Piece::Rook, side);
Boolean found;
for (i = 0; i < 4; i++)
{
square1 = loc;
found = False;
offset = 0;
const byte *data = BishopSquares[loc] + (8*i);
while (*data != 255)
{
Piece piece;
do
{
if (*data == 255) break;
square1 = *data++;
piece = board[square1];
} while (piece.IsEmpty());
if (piece == bishop || piece == queen)
{
found = True;
++n;
squares[index+offset] = square1;
if (indirect)
offset += Bearing::Offset;
else
break;
}
else
break;
}
if (found)
++index;
data = RookSquares[loc] + (8*i);
square1 = loc;
offset = 0;
found = False;
for (;;)
{
Piece piece;
do
{
if (*data == 255)
break;
square1 = *data++;
piece = board[square1];
} while (piece.IsEmpty());
if (piece == rook || piece == queen)
{
found = True;
++n;
squares[index+offset] = square1;
if (indirect)
offset += Bearing::Offset;
else
break;
}
else
break;
}
if (found)
++index;
}
return n;
}
unsigned
Bearing::Attack_or_Defend(const Board & board, const Square & loc,
Square * squares)
{
unsigned NumSquares = 0;
int j;
switch (board[loc].Type())
{
case Piece::Empty:
break;
case Piece::Pawn:
PawnMoves(board, board[loc].Color(),
loc, squares, NumSquares, True);
break;
case Piece::Knight:
KnightMoves(board, loc, squares, NumSquares, True);
break;
case Piece::Bishop:
for (j = 0; j < 4; j++)
{
const byte *data = BishopSquares[loc] + (j*8);
RBAttacks(board, data, squares, NumSquares);
}
break;
case Piece::Rook:
for (j = 0; j < 4; j++)
{
const byte *data = RookSquares[loc] + (j*8);
RBAttacks(board, data, squares, NumSquares);
}
break;
case Piece::Queen:
for (j = 0; j < 4; j++)
{
const byte *data = BishopSquares[loc] + (j*8);
RBAttacks(board, data, squares, NumSquares);
}
for (j = 0; j < 4; j++)
{
const byte *data = RookSquares[loc] + (j*8);
RBAttacks(board, data, squares, NumSquares);
}
break;
case Piece::King:
KingMoves(board, loc, squares, NumSquares, True);
break;
case Piece::Invalid:
break;
}
return NumSquares;
}
Boolean Bearing::Pinned( const Board &board, const Square loc,
Piece &PinnedByPiece,
Square &PinnedBySquare,
int &dir)
{
Piece p = board[loc];
if (p.IsEmpty() || p.Type() == Piece::King)
return False;
const ColorType side = p.Color();
const ColorType oside = OppositeColor(side);
// We "cheat" on constness by altering board[loc]. But we will
// put the original contents back .. honest
Piece &place = (Piece &)board[loc];
place = Piece::EmptyPiece(); // imagine me gone
Square ks(board.KingPos(side));
int offset = (int)loc - (int)ks;
int signOfOffset = Util::Sign(offset);
if (ks.File() == loc.File()) // possible pin on file
{
const byte *data
= (signOfOffset > 0) ? RookSquares[loc] + 8
: RookSquares[loc];
Square newsquare;
Piece attackPiece;
while (*data != 255)
{
newsquare = *data++;
attackPiece = board[newsquare];
if (!attackPiece.IsEmpty())
break;
}
if (attackPiece.Color() == oside && (
(attackPiece.Type() == Piece::Rook) ||
(attackPiece.Type() == Piece::Queen)))
{
place = p; // put piece back
PinnedBySquare = newsquare;
PinnedByPiece = attackPiece;
dir = ((int)newsquare - (int)loc > 0) ? RankIncr : -RankIncr;
return True;
}
}
if (ks.Rank(White) == loc.Rank(White)) // possible pin on rank
{
const byte *data = (signOfOffset > 0) ?
RookSquares[loc]+16 : RookSquares[loc]+24;
Square newsquare;
Piece attackPiece;
while (*data != 255)
{
newsquare = *data++;
attackPiece = board[newsquare];
if (!attackPiece.IsEmpty())
break;
}
if (attackPiece.Color() == oside && (
(attackPiece.Type() == Piece::Rook) ||
(attackPiece.Type() == Piece::Queen)))
{
place = p; // put piece back
PinnedBySquare = newsquare;
PinnedByPiece = attackPiece;
dir = ((int)newsquare > (int)loc) ? 1 : -1;
return True;
}
}
if (offset % 9 == 0) // possible diagonal pin
{
const byte *data
= (signOfOffset > 0) ? BishopSquares[loc] + 16
: BishopSquares[loc] + 8;
Square newsquare;
Piece attackPiece;
while (*data != 255)
{
newsquare = *data++;
attackPiece = board[newsquare];
if (!attackPiece.IsEmpty())
break;
}
if (attackPiece.Color() == oside && (
(attackPiece.Type() == Piece::Bishop) ||
(attackPiece.Type() == Piece::Queen)))
{
place = p; // put piece back
PinnedBySquare = newsquare;
PinnedByPiece = attackPiece;
dir = ((int)newsquare > (int)loc) ? 9 : -9;
return True;
}
}
if (offset % 7 == 0) // possible diagonal pin
{
const byte *data
= (signOfOffset > 0) ? BishopSquares[loc] + 24
: BishopSquares[loc];
Square newsquare;
Piece attackPiece;
while (*data != 255)
{
newsquare = *data++;
attackPiece = board[newsquare];
if (!attackPiece.IsEmpty())
break;
}
if (attackPiece.Color() == oside && (
(attackPiece.Type() == Piece::Bishop) ||
(attackPiece.Type() == Piece::Queen)))
{
place = p; // put piece back
PinnedBySquare = newsquare;
PinnedByPiece = attackPiece;
dir = ((int)newsquare > (int)loc) ? 7 : -7;
return True;
}
}
place = p;
return False;
}